package com.virtual.repository.common.model.adapters;

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.Unmarshaller;

import org.springframework.util.StringUtils;

import com.virtual.repository.common.model.CollectionProperty;
import com.virtual.repository.common.model.Mapping;
import com.virtual.repository.common.model.ModelConfiguration;
import com.virtual.repository.common.model.Property;

/**
 * The unmarshalling listener for model configuration. Calls before and after model configuration unmarshalling.
 * 
 * @author kchaber
 *
 */
public class ModelConfigUnmarshallListener extends Unmarshaller.Listener {
	
	@Override
	public void afterUnmarshal(Object target, Object parent) {
		if (!(target instanceof ModelConfiguration)) {
			return;
		}
		
		//after successful unmarshalling of the model configuration
		//we need to update properties map for each mapping and add to them the property, mapped by database entity name.
		
		//Additionally there is loading of primary key and foreign keys map for future fast reference
		ModelConfiguration modelConfiguration = (ModelConfiguration) target;

		if (modelConfiguration.getMappings() != null) {
			for (Mapping m : modelConfiguration.getMappings().values()) {
				if (m.getProperties() != null) {
					Map<String, Property> additionalProperties = new HashMap<>();
					Map<String, Property> foreignKeysProperties = new HashMap<>();
					
					for (Property p : m.getProperties().values()) {
						if (StringUtils.isEmpty(p.getSourceName())) {
							Mapping mapping = modelConfiguration.getMapping(p.getClassName());
							additionalProperties.put(mapping.getDbEntityName(), p);
						}

						//if property is primary key, then add its to the identifier field
						if (p.isPrimaryKey()) {
							m.setIdentifierProperty(p);
						}
						
						//if property is foreign key, then add its to the foreign keys map
						if (!StringUtils.isEmpty(p.getForeignKey())) {
							foreignKeysProperties.put(p.getForeignKey(), p);
						}
						
					}
					
					if (m.getCollections() != null) {
						Map<String, CollectionProperty> additionalCollections = new HashMap<>();
						
						for (CollectionProperty collection : m.getCollections().values()) {
							Mapping mapping = modelConfiguration.getMapping(collection.getPropertyClass());
							additionalCollections.put(mapping.getDbEntityName(), collection);
						}
						
						m.getCollections().putAll(additionalCollections);
					}

					m.getProperties().putAll(additionalProperties);
					m.setForeignKeys(foreignKeysProperties);
				}
			}
		}
	}

	@Override
	public void beforeUnmarshal(Object target, Object parent) {
		//don't need it at this moment
	}

}
